
#include <string.h>
#include <stdio.h>
#include <api_os.h>
#include <api_gps.h>
#include <api_event.h>
//#include <api_hal_uart.h>
#include <api_socket.h>
#include <api_network.h>
#include <api_debug.h>
#include "api_inc_gpio.h"
#include <api_hal_gpio.h>
#include "api_hal_pm.h"

#include "buffer.h"
#include "gps_parse.h"
#include "api_inc_time.h"
#include "time.h"

#include "frame.h"

#define MAIN_TASK_STACK_SIZE    (2048 * 4)
#define MAIN_TASK_PRIORITY      0
#define MAIN_TASK_NAME          "GPS Test Task"

static HANDLE gpsTaskHandle = NULL;


#define GPS_DATA_BUFFER_MAX_LENGTH 2048


Buffer_t gpsNmeaBuffer;
uint8_t  gpsDataBuffer[GPS_DATA_BUFFER_MAX_LENGTH];
uint8_t tmp[1024];

int socketFd = -1;

int TimeCount = 0;
unsigned int ErrorCount = 0;
bool PowerOnFlag = TRUE;

bool gprsStatus = FALSE;
bool gpsStatus = FALSE;


//char testUart[30];

GPS_Information_t* gpsInfo;

unsigned char SpeedValue[FliterN];
unsigned char FliterSpeed = 0;

GPIO_config_t gpioLedBlue = {
	.mode = GPIO_MODE_OUTPUT,
	.pin = GPIO_PIN25,
	.defaultLevel = GPIO_LEVEL_LOW
};

int FliterCount = 0;
void GpsUpdate()
{
	
    int32_t index = Buffer_Query(&gpsNmeaBuffer,"$GNVTG",strlen("$GNVTG"),Buffer_StartPostion(&gpsNmeaBuffer));
	
    if(index >= 0)
    {
        // Trace(1,"find $GNVTG");
        index = Buffer_Query(&gpsNmeaBuffer,"\r\n",strlen("\r\n"),index);
        if(index >= 0)
        {
            //Trace(2,"find complete GPS frame");
            
            memset(tmp,0,sizeof(tmp));
            uint32_t len = Buffer_Size2(&gpsNmeaBuffer,index)+1;
            //Trace(2,"frame len:%d",len);
            if(!Buffer_Gets(&gpsNmeaBuffer,tmp,len))
            {
                Trace(2,"get data from buffer fail");
				gpsStatus = FALSE;
                return;
            }
			gpsStatus = GPS_Parse(tmp);
			FliterCount++;
			SpeedValue[FliterCount] = myabs((int)gpsInfo->Speed);
			FliterSpeed = FliterCount == 4 ? filter() : FliterSpeed;
			Trace(2, "Speed:%d,Count:%d", FliterSpeed, FliterCount);
			FliterCount = FliterCount >= 4 ? -1 : FliterCount;
			//Trace(2, "gpsFlag:%d", gpsStatus);
        }
    }
}


// const uint8_t nmea[]="$GNGGA,000021.263,2228.7216,N,11345.5625,E,0,0,,153.3,M,-3.3,M,,*4E\r\n$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r\n$BDGSA,A,1,,,,,,,,,,,,,,,*0F\r\n$GPGSV,1,1,00*79\r\n$BDGSV,1,1,00*68\r\n$GNRMC,000021.263,V,2228.7216,N,11345.5625,E,0.000,0.00,060180,,,N*5D\r\n$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C\r\n";

void EventDispatch(API_Event_t* pEvent)
{
    //static uint8_t flag = 0;
	//RTC_Time_t* Time;
    switch(pEvent->id)
    {
        case API_EVENT_ID_GPS_UART_RECEIVED:
            //Trace(2,"received GPS data,length:%d, data:%s,flag:%d",pEvent->param1,pEvent->pParam1,flag);
            Buffer_Puts(&gpsNmeaBuffer,pEvent->pParam1,pEvent->param1);
            GpsUpdate();
            break;
			/*
        case API_EVENT_ID_UART_RECEIVED:
            if(pEvent->param1 == UART1)
            {
                uint8_t data[pEvent->param2+1];
                data[pEvent->param2] = 0;
                memcpy(data,pEvent->pParam1,pEvent->param2);
                Trace(1,"uart received data,length:%d,data:%s",pEvent->param2,data);
            }
            break;*/
        case API_EVENT_ID_NETWORK_REGISTERED_HOME:
        case API_EVENT_ID_NETWORK_REGISTERED_ROAMING:
            Trace(2,"register success");

            //flag = 1;
			Network_StartAttach();
			break;

		case API_EVENT_ID_NETWORK_ATTACHED:
			Trace(2, "network attach success");
			Network_PDP_Context_t context = {
				.apn = "cmnet",
				.userName = ""    ,
				.userPasswd = ""
			};
			Network_StartActive(context);
			break;

		case API_EVENT_ID_NETWORK_ACTIVATED:
			socketFd = Socket_TcpipConnect(TCP, SERVER_IP, SERVER_PORT);
			Trace(2, "network activate success");
			break;
		case API_EVENT_ID_SOCKET_CONNECTED:
			Trace(2, "tcp connected!!!");
			gprsStatus = TRUE;
			ErrorCount = 0;
			break;
		case API_EVENT_ID_SOCKET_SENT:
			Trace(2, "tcp sended!!!");
			gprsStatus = TRUE;
			ErrorCount = 0;
			Count++;
			break;
		case API_EVENT_ID_SOCKET_ERROR:
			Trace(2, "error!!!");
			Socket_TcpipClose(socketFd);
			socketFd = Socket_TcpipConnect(TCP, SERVER_IP, SERVER_PORT);
			//PM_Restart();
			ErrorCount++;
			gprsStatus = FALSE;

				//gprsStatus = FALSE;
				break;
				/*
		case API_EVENT_ID_NETWORK_GOT_TIME:
			//TIME_SetIsAutoUpdateRtcTime(TRUE);
			Time = pEvent->pParam1;
			//TIME_SetRtcTime(Time);
			Trace(2, "Time Year:%d month:%d day:%d hour:%d min:%d sec:%d", Time->year, Time->month, Time->day, Time->hour, Time->minute, Time->second);
			break;*/
		case API_EVENT_ID_SOCKET_CLOSED:
			socketFd = Socket_TcpipConnect(TCP, SERVER_IP, SERVER_PORT);
			ErrorCount++;
        default:
            break;
    }
}

void ledBlink(GPIO_PIN pin, int times)
{
	gpioLedBlue.pin = pin;
	for (int i = 0; i < times; i++)
	{
		GPIO_SetLevel(gpioLedBlue, GPIO_LEVEL_HIGH);
		OS_Sleep(300);
		GPIO_SetLevel(gpioLedBlue, GPIO_LEVEL_LOW);
		OS_Sleep(200);
	}
}


void gps_testTask(void *pData)
{
	
	gpsInfo = Gps_GetInfo();
    while(1)
    {
		if (PowerOnFlag&&gprsStatus)
		{
			login_frame();
			Socket_TcpipWrite(socketFd, frame, 18);
			PowerOnFlag = FALSE;
		}
		if (!gprsStatus)
		{
			socketFd = Socket_TcpipConnect(TCP, SERVER_IP, SERVER_PORT);
		}
		if (ErrorCount >= 30)
		{
			PM_Restart();
			//socketFd = Socket_TcpipConnect(TCP, SERVER_IP, SERVER_PORT);
			//ErrorCount = 0;
		}
		if (Count >= 0x7fffffff)
		{
			PM_Restart();
			Count = 0;

		}
		//Trace(2, "Gps:%dLong:%s,lat:%s", gpsInfo->fixGPS, gpsInfo->longitude, gpsInfo->latitude);
		ledBlink(GPIO_PIN_LED_BLUE, gpsInfo->fixGPS);
		if (gpsInfo->fixGPS > 1)
		{
			Trace(2, "Speed:%d", FliterSpeed);
			gpsStatus = TRUE;
			//gpsFrame(gpsInfo)
			
		}
		else
		{
			
			gpsStatus = FALSE;
		}
		if (!gprsStatus)
		{
			ErrorCount++;
			gpioLedBlue.pin = GPIO_PIN_LED_BLUE;
			GPIO_SetLevel(gpioLedBlue, GPIO_LEVEL_HIGH);
			gpioLedBlue.pin = GPIO_PIN_LED_GREEN;
			GPIO_SetLevel(gpioLedBlue, GPIO_LEVEL_HIGH);
		}
		else
		{
			gpioLedBlue.pin = GPIO_PIN_LED_GREEN;
			GPIO_SetLevel(gpioLedBlue, GPIO_LEVEL_LOW);
		}
		++TimeCount;
		if (TimeCount % 6==0)
		{
			
			if (gpsStatus&&gprsStatus&& FliterSpeed>=1)
			{
				Trace(2, "ready to send gpsFrame");
				gpsFrame(gpsInfo);
				Socket_TcpipWrite(socketFd, frame, 28);
				Trace(2, "Time:%s Date:%s lan:%s lon:%s", gpsInfo->UTC_Time, gpsInfo->UTC_Date, gpsInfo->latitude, gpsInfo->longitude);
				ledBlink(GPIO_PIN_LED_GREEN, 2);

			}
			if (gprsStatus)
			{
				status_frame(gpsStatus);
				Socket_TcpipWrite(socketFd, frame, 15);
			}
			else
			{
				TimeCount = 0;
			}
		}
		OS_Sleep(2000);
    }
}


void gps_MainTask(void *pData)
{
    API_Event_t* event=NULL;

	
	for (int i = 0; i<GPIO_PIN_MAX; ++i)
	{
		gpioLedBlue.pin = i;
		GPIO_Init(gpioLedBlue);
	}

    GPS_Open(NULL);
	
    Buffer_Init(&gpsNmeaBuffer,gpsDataBuffer,GPS_DATA_BUFFER_MAX_LENGTH);
    OS_CreateTask(gps_testTask,
            NULL, NULL, MAIN_TASK_STACK_SIZE, MAIN_TASK_PRIORITY, 0, 0, MAIN_TASK_NAME);
    while(1)
    {
        if(OS_WaitEvent(gpsTaskHandle, (void**)&event, OS_TIME_OUT_WAIT_FOREVER))
        {
            EventDispatch(event);
            OS_Free(event->pParam1);
            OS_Free(event->pParam2);
            OS_Free(event);
			/*
			if (event->pParam2 != NULL)
			{
				event->pParam2 = NULL;
			}
			if (event->pParam1 != NULL)
			{
				event->pParam1 = NULL;
			}
			if (event != NULL)
			{
				event = NULL;
			}*/
			
        }

    }
}


void gps_Main(void)
{
    gpsTaskHandle = OS_CreateTask(gps_MainTask,
        NULL, NULL, MAIN_TASK_STACK_SIZE, MAIN_TASK_PRIORITY, 0, 0, MAIN_TASK_NAME);
    OS_SetUserMainHandle(&gpsTaskHandle);
}

